// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

/*
Package zlib implements reading and writing of zlib format compressed data,
as specified in RFC 1950.

The implementation provides filters that uncompress during reading
and compress during writing.  For example, to write compressed data
to a buffer:

	var b bytes.Buffer
	w := zlib.NewWriter(&b)
	w.Write([]byte("hello, world\n"))
	w.Close()

and to read that data back:

	r, err := zlib.NewReader(&b)
	io.Copy(os.Stdout, r)
	r.Close()
*/
package zlib

import (
	"bufio"
	"compress/flate"
	"errors"
	"hash"
	"hash/adler32"
	"io"
)

const zlibDeflate = 8

var (
	// 读取校验和无效的ZLIB数据时返回ErrChecksum。
	ErrChecksum = errors.New("zlib: invalid checksum")
	// ErrDictionary在读取包含无效字典的ZLIB数据时返回。
	ErrDictionary = errors.New("zlib: invalid dictionary")
	// 读取头无效的ZLIB数据时返回ErrHeader。
	ErrHeader = errors.New("zlib: invalid header")
)

type reader struct {
	r            flate.Reader
	decompressor io.ReadCloser
	digest       hash.Hash32
	err          error
	scratch      [4]byte
}

// 重置程序重置NewReader或NewReaderDict返回的ReadCloser，以切换到新的底层读卡器。这允许重用ReadCloser 
// 而不是分配一个新的。
type Resetter interface {
	// 重置丢弃所有缓冲数据，并重置重置器，就像它是
	// 用给定读取器新初始化的一样。
	Reset(r io.Reader, dict []byte) error
}

// NewReader创建一个新的ReadCloser。
// 从返回的ReadCloser读取数据，并从r解压缩数据。
// 如果r未实现io。通过读卡器，解压器可能从r中读取的
// 数据超过需要。
// 完成后，调用方有责任调用ReadCloser关闭。
// 
// NewReader返回的ReadCloser也实现了重置。
func NewReader(r io.Reader) (io.ReadCloser, error) {
	return NewReaderDict(r, nil)
}

// NewReaderDict与NewReader类似，但使用预设词典。
// 如果压缩数据没有引用字典，NewReaderDict将忽略字典。
// 如果压缩的数据指向不同的字典，NewReaderDict将返回ErrDictionary。
// 
// NewReaderDict返回的ReadCloser也执行重置。
func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
	z := new(reader)
	err := z.Reset(r, dict)
	if err != nil {
		return nil, err
	}
	return z, nil
}

func (z *reader) Read(p []byte) (int, error) {
	if z.err != nil {
		return 0, z.err
	}

	var n int
	n, z.err = z.decompressor.Read(p)
	z.digest.Write(p[0:n])
	if z.err != io.EOF {
		// 在正常情况下，我们返回这里。
		return n, z.err
	}

	// 完成文件；检查校验和。
	if _, err := io.ReadFull(z.r, z.scratch[0:4]); err != nil {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
		z.err = err
		return n, z.err
	}
	// ZLIB（RFC 1950）是大端的，不同于GZIP（RFC 1952）。
	checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
	if checksum != z.digest.Sum32() {
		z.err = ErrChecksum
		return n, z.err
	}
	return n, io.EOF
}

// 调用Close不会关闭包装的io。Reader最初传递给NewReader。
// 为了验证ZLIB校验和，读卡器必须在io之前被完全消耗。EOF。
func (z *reader) Close() error {
	if z.err != nil && z.err != io.EOF {
		return z.err
	}
	z.err = z.decompressor.Close()
	return z.err
}

func (z *reader) Reset(r io.Reader, dict []byte) error {
	*z = reader{decompressor: z.decompressor}
	if fr, ok := r.(flate.Reader); ok {
		z.r = fr
	} else {
		z.r = bufio.NewReader(r)
	}

	// 阅读标题（RFC 1950第2.2节）。
	_, z.err = io.ReadFull(z.r, z.scratch[0:2])
	if z.err != nil {
		if z.err == io.EOF {
			z.err = io.ErrUnexpectedEOF
		}
		return z.err
	}
	h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
	if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
		z.err = ErrHeader
		return z.err
	}
	haveDict := z.scratch[1]&0x20 != 0
	if haveDict {
		_, z.err = io.ReadFull(z.r, z.scratch[0:4])
		if z.err != nil {
			if z.err == io.EOF {
				z.err = io.ErrUnexpectedEOF
			}
			return z.err
		}
		checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
		if checksum != adler32.Checksum(dict) {
			z.err = ErrDictionary
			return z.err
		}
	}

	if z.decompressor == nil {
		if haveDict {
			z.decompressor = flate.NewReaderDict(z.r, dict)
		} else {
			z.decompressor = flate.NewReader(z.r)
		}
	} else {
		z.decompressor.(flate.Resetter).Reset(z.r, dict)
	}
	z.digest = adler32.New()
	return nil
}
